v 您所在的位置:网站首页 vue v model的原理 v

v

#v| 来源: 网络整理| 查看: 265

v-model双向绑定的实现原理

Object.defineProperty劫持数据时存在两大缺陷:

1.下标方式修改数组数据

2.给对象新增属性

均不会触发组件的重新渲染,因为Object.defineProperty不能拦截到这些操作,更精确的来说,对于数组而言,大部分操作都是拦截不到的.vue内部通过重写函数的方式解决了这个问题。

缺陷的解决:

1.vue提供了一个API进行解决

2.对于数组而言,vue内部重写了以下函数实现派发更新

Object.defineProperty()在set中赋值=>触发update方法进行节点更新=>实现v-model双向数据绑定

input触发:

set数据改变执行那个update

 update更新DOM节点中的内容

Object.defineProperty劫持数据时存在两大缺陷: 1.下标方式修改数组数据 2.给对象新增属性 均不会触发组件的重新渲染,因为Object.defineProperty不能拦截到这些操作,更精确的来说,对于数组而言,大部分操作都是拦截不到的.vue内部通过重写函数的方式解决了这个问题。 缺陷的解决: 1.vue提供了一个API进行解决 export function set (target: Array | Object, key: any, val: any): any { // 判断是否为数组且下标是否有效 if (Array.isArray(target) && isValidArrayIndex(key)) { // 调用 splice 函数触发派发更新 // 该函数已被重写 target.length = Math.max(target.length, key) target.splice(key, 1, val) return val } // 判断 key 是否已经存在 if (key in target && !(key in Object.prototype)) { target[key] = val return val } const ob = (target: any).__ob__ // 如果对象不是响应式对象,就赋值返回 if (!ob) { target[key] = val return val } // 进行双向绑定 defineReactive(ob.value, key, val) // 手动派发更新 ob.dep.notify() return val } 2.对于数组而言,vue内部重写了以下函数实现派发更新 // 获得数组原型 const arrayProto = Array.prototype export const arrayMethods = Object.create(arrayProto) // 重写以下函数 const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] methodsToPatch.forEach(function (method) { // 缓存原生函数 const original = arrayProto[method] // 重写函数 def(arrayMethods, method, function mutator (...args) { // 先调用原生函数获得结果 const result = original.apply(this, args) const ob = this.__ob__ let inserted // 调用以下几个函数时,监听新数据 switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) // 手动派发更新 ob.dep.notify() return result }) }) Object.defineProperty()


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有